home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 30
/
Mac Magazin and MacEasy Magazine CD - Issue 30.iso
/
utilities
/
Mac OS X
/
Flurry
/
Flurry source
/
Source Folder
/
Smoke.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2002-01-25
|
11KB
|
414 lines
// Smoke.cpp: implementation of the Smoke class.
//
//////////////////////////////////////////////////////////////////////
#include "Std.h"
#include "Smoke.h"
#include "Spark.h"
#include "Star.h"
extern Spark spark[12];
extern Star star;
extern float gravity;
#define MAXANGLES 16384
#define NOT_QUITE_DEAD 3
inline float FastDistance2D(float x, float y)
{
// this function computes the distance from 0,0 to x,y with ~3.5% error
// first compute the absolute value of x,y
x = (x < 0.0f) ? -x : x;
y = (y < 0.0f) ? -y : y;
// compute the minimum of x,y
float mn = min(x,y);
// return the distance
return(x+y-(mn*0.5f)-(mn*0.25f)+(mn*0.0625f));
} // end FastDistance2D
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
float intensity = 75000.0f;
Smoke::Smoke()
{
}
Smoke::~Smoke()
{
}
void Smoke::Update()
{
static int nextParticle = 0;
static float lastParticleTime = 0.25f;
int i,j;
static float old[3];
static int firstTime = 1;
static long frame = 0;
float mPosX;
float mPosY;
float mPosZ;
float sx = star.position[0];
float sy = star.position[1];
float sz = star.position[2];
frame++;
if (!firstTime)
{
// release 12 puffs every frame
if (fTime-lastParticleTime >= 1.0f / 121.0f)
{
float dx,dy,dz;
float f;
float rsquared;
int whichSpark = 0;
float mag;
dx = old[0] - sx;
dy = old[1] - sy;
dz = old[2] - sz;
//rsquared = (dx*dx+dy*dy+dz*dz);
mag = 5.0f;// / (float) sqrt(rsquared);
float deltax = (dx * mag);
float deltay = (dy * mag);
float deltaz = (dz * mag);
for (i=0;i<numStreams;i++)
{
p[nextParticle].delta[0] = deltax;
p[nextParticle].delta[1] = deltay;
p[nextParticle].delta[2] = deltaz;
p[nextParticle].position[0] = sx;
p[nextParticle].position[1] = sy;
p[nextParticle].position[2] = sz;
p[nextParticle].oldposition[0] = sx;
p[nextParticle].oldposition[1] = sy;
p[nextParticle].oldposition[2] = sz;
float streamSpeedCoherenceFactor = max(0.0f,1.0f + RandBell(0.25f*incohesion));
if (MouseDown)
{
mPosZ = sz;
mPosX = (MouseX - sys_glWidth * 0.5f) / (sys_glWidth / mPosZ);
mPosY = (sys_glHeight * 0.5f - MouseY) / (sys_glWidth / mPosZ);
dx = p[nextParticle].position[0] - mPosX;
dy = p[nextParticle].position[1] - mPosY;
dz = p[nextParticle].position[2] - mPosZ;
rsquared = (dx*dx+dy*dy+dz*dz);
mag = streamSpeed * 0.05f * streamSpeedCoherenceFactor / (float) sqrt(rsquared);
p[nextParticle].delta[0] -= (dx * mag);
p[nextParticle].delta[1] -= (dy * mag);
p[nextParticle].delta[2] -= (dz * mag);
}
dx = p[nextParticle].position[0] - spark[i].position[0];
dy = p[nextParticle].position[1] - spark[i].position[1];
dz = p[nextParticle].position[2] - spark[i].position[2];
rsquared = (dx*dx+dy*dy+dz*dz);
f = streamSpeed * streamSpeedCoherenceFactor;
mag = f / (float) sqrt(rsquared);
p[nextParticle].delta[0] -= (dx * mag);
p[nextParticle].delta[1] -= (dy * mag);
p[nextParticle].delta[2] -= (dz * mag);
p[nextParticle].color[0] = spark[i].color[0] * (1.0f + RandBell(colorIncoherence));// + RandBell(0.25f*colorIncoherence);
p[nextParticle].color[1] = spark[i].color[1] * (1.0f + RandBell(colorIncoherence));// + RandBell(0.25f*colorIncoherence);
p[nextParticle].color[2] = spark[i].color[2] * (1.0f + RandBell(colorIncoherence));// + RandBell(0.25f*colorIncoherence);
p[nextParticle].color[3] = 0.85f * (1.0f + RandBell(0.5f*colorIncoherence));// + RandBell(0.125f*colorIncoherence);
p[nextParticle].dead = FALSE;
p[nextParticle].time = fTime;
p[nextParticle].animFrame = rand()&63;
nextParticle++;
if (nextParticle == NUMSMOKEPARTICLES)
{
nextParticle = 0;
}
}
lastParticleTime = fTime;
}
}
else
{
lastParticleTime = fTime;
firstTime = 0;
}
for (i=0;i<3;i++)
{
old[i] = star.position[i];
}
if (MouseDown)
{
mPosZ = seraphDistance;
mPosX = (MouseX - sys_glWidth * 0.5f) / (sys_glWidth / mPosZ);
mPosY = (sys_glHeight * 0.5f - MouseY) / (sys_glWidth / mPosZ);
}
// double frameRate = ((double) dframe)/(fTime -fTimeOffset);
double frameRateModifier = fDeltaTime * 42.5f;
// double frameRateModifier = 42.5f / frameRate;
for (i=0;i<NUMSMOKEPARTICLES;i++)
{
if (p[i].dead)
{
continue;
}
float dx,dy,dz;
float f;
float rsquared;
float mag;
float deltax = p[i].delta[0];
float deltay = p[i].delta[1];
float deltaz = p[i].delta[2];
// if (MouseDown)
// {
// mPosZ = (p[i].position[2] + star.position[2]) * 0.5f;
// mPosX = (MouseX - sys_glWidth * 0.5f) / (sys_glWidth / mPosZ);
// mPosY = (sys_glHeight * 0.5f - MouseY) / (sys_glWidth / mPosZ);
// }
for (j=0;j<numStreams;j++)
{
dx = p[i].position[0] - spark[j].position[0];
dy = p[i].position[1] - spark[j].position[1];
dz = p[i].position[2] - spark[j].position[2];
rsquared = (dx*dx+dy*dy+dz*dz);
f = (gravity/rsquared) * frameRateModifier;
if ((i % numStreams) == j)
{
// if (MouseDown)
// {
// f *= 1.0f + streamBias * 0.25f;
// }
// else
// {
f *= 1.0f + streamBias;
// }
}
mag = f / (float) sqrt(rsquared);
deltax -= (dx * mag);
deltay -= (dy * mag);
deltaz -= (dz * mag);
}
if (MouseDown)
{
dx = p[i].position[0] - mPosX;
dy = p[i].position[1] - mPosY;
dz = p[i].position[2] - mPosZ;
rsquared = (dx*dx+dy*dy+dz*dz);
f = (gravity/rsquared) * frameRateModifier;
f *= (1.0f + streamBias) * 0.5f;
mag = f / (float) sqrt(rsquared) ;
deltax -= (dx * mag);
deltay -= (dy * mag);
deltaz -= (dz * mag);
}
// slow this particle down by drag
deltax *= drag;
deltay *= drag;
deltaz *= drag;
if ((deltax*deltax+deltay*deltay+deltaz*deltaz) >= 25000000.0f)
{
p[i].dead = TRUE;
continue;
}
// update the position
p[i].delta[0] = deltax;
p[i].delta[1] = deltay;
p[i].delta[2] = deltaz;
for (j=0;j<3;j++)
{
p[i].oldposition[j] = p[i].position[j];
p[i].position[j] += p[i].delta[j]*fDeltaTime;
}
}
}
void Smoke::Draw()
{
static float seraphimVertices[NUMSMOKEPARTICLES*2*4];
static float seraphimColors[NUMSMOKEPARTICLES*4*4];
static float seraphimTextures[NUMSMOKEPARTICLES*2*4];
int svi = 0;
int sci = 0;
int sti = 0;
int si = 0;
float width,sx,sy;
float u0,v0,u1,v1;
float w,z;
static int firstTime = 1;
if (firstTime)
{
firstTime = 0;
}
static long frame = 0;
static float lastFrameTime = 0.0f;
{
frame++;
lastFrameTime = fTime;
}
float screenRatio = sys_glWidth / 1024.0f;
width = (streamSize+2.5f*streamExpansion) * screenRatio;
// glBegin(GL_QUADS);
float hslash2 = sys_glHeight * 0.5f;
float wslash2 = sys_glWidth * 0.5f;
for (int i=0;i<NUMSMOKEPARTICLES;i++)
{
if (p[i].dead == TRUE)
{
continue;
}
float thisWidth = (streamSize+(fTime-p[i].time)*streamExpansion) * screenRatio;
if (thisWidth >= width)
{
p[i].dead = TRUE;
continue;
}
z = p[i].position[2];
sx = p[i].position[0] * sys_glWidth / z + wslash2;
sy = p[i].position[1] * sys_glWidth / z + hslash2;
float oldz = p[i].oldposition[2];
if (sx > sys_glWidth+50.0f || sx < -50.0f || sy > sys_glHeight+50.0f || sy < -50.0f || z < 25.0f || oldz < 25.0f)
{
continue;
}
w = max(1.0f,thisWidth/z);
// if (p[i].dead == NOT_QUITE_DEAD)
// {
// w *= 0.25f;
// }
float oldx = p[i].oldposition[0];
float oldy = p[i].oldposition[1];
float oldscreenx = (oldx * sys_glWidth / oldz) + wslash2;
float oldscreeny = (oldy * sys_glWidth / oldz) + hslash2;
float dx = (sx-oldscreenx);
float dy = (sy-oldscreeny);
float d = FastDistance2D(dx, dy);
float s;
if (d)
{
s = w/d;
}
else
{
s = 0.0f;
}
float os;
float ow = max(1.0f,thisWidth/oldz);
if (d)
{
os = ow/d;
}
else
{
os = 0.0f;
}
float m = 1.0f + s;
float dxs = dx*s;
float dys = dy*s;
float dxos = dx*os;
float dyos = dy*os;
float dxm = dx*m;
float dym = dy*m;
p[i].animFrame++;
if (p[i].animFrame >= 64)
{
p[i].animFrame = 0;
}
u0 = (p[i].animFrame&&7) * 0.125f;
v0 = (p[i].animFrame>>3) * 0.125f;
u1 = u0 + 0.125f;
v1 = v0 + 0.125f;
u1 = u0 + 0.125f;
v1 = v0 + 0.125f;
float cm = (1.375f - thisWidth/width);
if (p[i].dead == 3)
{
cm *= 0.125f;
p[i].dead = TRUE;
}
// glColor4f(p[i].color[0]*cm,p[i].color[1]*cm,p[i].color[2]*cm,p[i].color[3]*cm);
si++;
float cm0 = p[i].color[0]*cm;
float cm1 = p[i].color[1]*cm;
float cm2 = p[i].color[2]*cm;
float cm3 = p[i].color[3]*cm;
seraphimColors[sci++] = cm0;
seraphimColors[sci++] = cm1;
seraphimColors[sci++] = cm2;
seraphimColors[sci++] = cm3;
seraphimColors[sci++] = cm0;
seraphimColors[sci++] = cm1;
seraphimColors[sci++] = cm2;
seraphimColors[sci++] = cm3;
seraphimColors[sci++] = cm0;
seraphimColors[sci++] = cm1;
seraphimColors[sci++] = cm2;
seraphimColors[sci++] = cm3;
seraphimColors[sci++] = cm0;
seraphimColors[sci++] = cm1;
seraphimColors[sci++] = cm2;
seraphimColors[sci++] = cm3;
// glTexCoord2f(u0,v0);
seraphimTextures[sti++] = u0;
seraphimTextures[sti++] = v0;
// glVertex2f(sx+dxm-dys,sy+dym+dxs);
seraphimVertices[svi++] = sx+dxm-dys;
seraphimVertices[svi++] = sy+dym+dxs;
// glTexCoord2f(u0,v1);
seraphimTextures[sti++] = u0;
seraphimTextures[sti++] = v1;
// glVertex2f(sx+dxm+dys,sy+dym-dxs);
seraphimVertices[svi++] = sx+dxm+dys;
seraphimVertices[svi++] = sy+dym-dxs;
// glTexCoord2f(u1,v1);
seraphimTextures[sti++] = u1;
seraphimTextures[sti++] = v1;
// glVertex2f(oldscreenx-dxm+dyos,oldscreeny-dym-dxos);
seraphimVertices[svi++] = oldscreenx-dxm+dyos;
seraphimVertices[svi++] = oldscreeny-dym-dxos;
// glTexCoord2f(u1,v0);
seraphimTextures[sti++] = u1;
seraphimTextures[sti++] = v0;
// glVertex2f(oldscreenx-dxm-dyos,oldscreeny-dym+dxos);
seraphimVertices[svi++] = oldscreenx-dxm-dyos;
seraphimVertices[svi++] = oldscreeny-dym+dxos;
}
// glEnd();
glColorPointer(4,GL_FLOAT,0,seraphimColors);
glVertexPointer(2,GL_FLOAT,0,seraphimVertices);
glTexCoordPointer(2,GL_FLOAT,0,seraphimTextures);
glDrawArrays(GL_QUADS,0,si*4);
}